/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "iot_cloud.h"
#include "iot_wifi.h"
#include <stdio.h>
#include "ohos_init.h"
#include "hcsr04_control.h"
#include "iot_log.h"
#include "kv_store.h"
#include "cjson/cJSON.h"
#include "cmsis_os2.h"
#include "iot_boardled_xradio.h"
#include "iot_boardbutton_xradio.h"

#define CONFIG_SLEEP                    5
#define CONFIG_TASK_MAIN_PRIOR          24
#define CONFIG_TASK_MAIN_STACKSIZE      (4*1024)
#define CLOUD_DEFAULT_SERVERIP          "121.36.42.100"     // replace it with iotplatform server ip
#define CLOUD_DEFAULT_SERVERPORT        "1883"              // replace it with iotplatform server  port
#define CONFIG_TASK_DEFAULT_STACKSIZE   (2 * 1024)         // unit:bytes
#define CONFIG_TASK_DEFAULT_PRIOR       20                 // default task priority
#define CONFIG_TASK_TASK_PRIOR       21                 // default task priority
#define CONFIG_SENSOR_SAMPLE_CYCLE      700              // unit:minisecond
#define CMD_KEY    "cmd"
#define PAR_KEY    "param"
#define SID_KEY    "wifiname"
#define PWD_KEY    "wifipassword"
#define HEIGHT_KEY "height"
#define WEIGHT_KEY "weight"
#define CONNECT_FAILED     -1
#define CONNECT_SUCCESS    0
#define DATA_PATH    "/"


static g_status_connect_cloud = CONNECT_FAILED;


typedef struct {
    char weight[10];
    char height[10];
} SmartElectronicScaleInfo;


int CLOUD_CommandCallBack(const char *jsonString)
{
    return 0;
}

static int IotWifiInfo_get(char *ssid, int id_size, char *pwd, int pd_size)
{
    int retval = UtilsGetValue(SID_KEY, ssid, id_size);
    if (retval <= 0) {
    LOG_E("no such ssid stored! retval=%d\n", retval);
        return -1;
    }
    if (UtilsGetValue(PWD_KEY, pwd, pd_size) < 0) {
        LOG_E("ssid(%s) no password stored! \n", ssid);
    } else {
        LOG_E("ssid : %s, pwd : %s! \n", ssid, pwd);
    }
    return 0;
}

static void IotWifiInfo_set(char *ssid, int id_size, char *pwd, int pd_size)
{
    int res = 0;
    if ((res = UtilsSetValue(SID_KEY, ssid)) != 0) {
        LOG_E("store ssid failed! res=%d\n", res);
        return;
    }
    if ((res = UtilsSetValue(PWD_KEY, pwd)) != 0) {
        LOG_E("store password failed! res=%d \n", res);
        UtilsDeleteValue(SID_KEY);
        return;
    }
    LOG_E("store password success! \n");
}


static int IotProfile_Report(SmartElectronicScaleInfo *info)
{
    if (info == NULL) {
        return -1;
    }
    if (g_status_connect_cloud == CONNECT_FAILED) {
        return -1;
    }
    int ret = -1;
    cJSON *root = NULL;
    char *jsonString;
    IotProfileService service;
    IotProfileKV kvWeight, kvHeight;

    /* package the data */
    service.eventTime = NULL;
    service.serviceID = "SmartElectronicScale";
    service.propertyLst = &kvWeight;
    service.nxt = NULL;

    kvWeight.key = "weight";
    kvWeight.value = (info->weight);
    kvWeight.type = IOT_PROFILE_KEY_DATATYPE_STRING;
    kvWeight.nxt = &kvHeight;

    kvHeight.key = "height";
    kvHeight.value = (info->height);
    kvHeight.type = IOT_PROFILE_KEY_DATATYPE_STRING;
    kvHeight.nxt = NULL;

    jsonString = IoTProfilePackage(&service);
    if (NULL != jsonString) {
        LOG_I(, "jsonString:%s", jsonString);

        ret = CLOUD_ReportMsg(jsonString);
        free(jsonString);
    } else {
        LOG_E("format the report message error");
    }
    return ret;
}

static void ButtonEventHandle(void *event)
{
    int res = 0;
    float height, weight;
#define MAX_LENGTH 10
#define HEIGHT_ENLARGE 100
#define WEIGHT_ENLARGE 1000
    char h[MAX_LENGTH], w[MAX_LENGTH];
    Hcsr04SetInitHeight(res);
    Hx711SetInitWeight(res);

    LOG_I("buttonEventCallback!\n");
    GetMeasurementDistance(&height);
    GetMeasurementWeight(&weight);

    int hght = height * HEIGHT_ENLARGE;
    int wght = weight * WEIGHT_ENLARGE;

    if (sprintf_s(h, MAX_LENGTH, "%d", hght) < 0) {
        printf("sprintf fail\n");
    }
    if (sprintf_s(w, MAX_LENGTH, "%d", wght) < 0) {
        printf("sprintf fail\n");
    }
    if ((res = UtilsSetValue(HEIGHT_KEY, h)) != 0) {
        LOG_E("store height failed! res=%d\n", res);
        return;
    }
    if ((res = UtilsSetValue(WEIGHT_KEY, w)) != 0) {
        LOG_E("store weight failed! res=%d \n", res);
        return;
    }
    Hcsr04SetInitHeight(hght);
    Hx711SetInitWeight(wght);
}

static int InitHeightAndWeight(void)
{
#define MAX_LENGTH 10
    char h[MAX_LENGTH], w[MAX_LENGTH];

    if (UtilsGetValue(HEIGHT_KEY, h, MAX_LENGTH) < 0) {
        LOG_E("get height failed! height=%s\n", h);
        return;
    }

    if (UtilsGetValue(WEIGHT_KEY, w, MAX_LENGTH) < 0) {
        LOG_E("get weight failed! weight=%s\n", w);
        return;
    }

    int hght;
    int wght;
    if (sscanf_s(h, "%d", &hght,sizeof(hght)) < 0) {
        printf("sscanf_s failed\n");
    }
    if (sscanf_s(w, "%d", &wght,sizeof(wght)) < 0) {
        printf("sscanf_s failed\n");
    }

    Hcsr04SetInitHeight(hght);
    Hx711SetInitWeight(wght);

    return 1;
}


static void TaskThread(void)
{
    Hx711InitRegisterIO();
    Hcs04InitRegisterIO();
    float weight, height;
#define MAX 10
    while (1) {
        SmartElectronicScaleInfo reportInfo;
        GetMeasurementDistance(&height);
        GetMeasurementWeight(&weight);

        if (sprintf_s(reportInfo.weight, MAX, "%.2f", weight) < 0) {
            printf("sprintf_s\n");
        }
        if (sprintf_s(reportInfo.height, MAX, "%.2f", height) < 0) {
            printf("sprintf_s\n");
        }

        IotProfile_Report(&reportInfo);
        OS_MSleep(CONFIG_SENSOR_SAMPLE_CYCLE);
    }
}


static void MainThread(void)
{
    const char *app_name = "teamX-SmartElectronicScale";
    const char *deviceID = "61bae58c2b2aa20288c5f467_SmartElectronicScale";
    const char *devicePSK = "12345678";
    int button_pressed;
    char ssid[128] = {0};
    char psk[128] = {0};

    UtilsSetEnv(DATA_PATH);

    button_pressed = Board_IsButtonPressed();
    Board_ButtonInit(ButtonEventHandle);
    LedFlashFrequencySet(LED_FLASH_FAST);

    if (button_pressed) {
        if (BOARD_NetCfgStartConfig(app_name, ssid, sizeof(ssid), psk, sizeof(psk)) < 0) {
            LOG_E("BOARD_NetCfgStartConfig failed!");
            return;
        }
    } else {
        button_pressed = IotWifiInfo_get(ssid, sizeof(ssid), psk, sizeof(psk));
        if (button_pressed != 0) {
            button_pressed = 1;
            if (BOARD_NetCfgStartConfig(app_name, ssid, sizeof(ssid), psk, sizeof(psk)) < 0) {
                LOG_E("BOARD_NetCfgStartConfig failed!");
                return;
            }
        }
    }
    InitHeightAndWeight();
    LedFlashFrequencySet(LED_FLASH_NORMAL);
    LOG_I("config network ok! start connect the network!");
    if (BOARD_ConnectWifi((const char *)ssid, (const char *)psk) != 0) {
        LOG_E("connect wifi failed! ssid:%s, psk:%s", ssid, psk);
        return;
    }
    LOG_I("connect network success!");
    if (button_pressed) {
        IotWifiInfo_set(ssid, sizeof(ssid), psk, sizeof(psk));
    }
    LedFlashFrequencySet(LED_FLASH_SLOW);
    sleep(CONFIG_SLEEP);
    if (CLOUD_Init() != 0) {
        LOG_E("CLOUD_Init failed!");
        return;
    }
    g_status_connect_cloud = CLOUD_Connect(deviceID, devicePSK, CLOUD_DEFAULT_SERVERIP, CLOUD_DEFAULT_SERVERPORT);
    if (g_status_connect_cloud != 0) {
        LedFlashFrequencySet(LED_FLASH_FAST_PLUGS);
        LOG_E("CLOUD_Connect failed!");
        return;
    }
    LedFlashFrequencySet(LED_FLASH_SLOW_PLUGS);
}


static void SmartElectronicScaleEntry(void)
{
    LOG_I("SmartElectronicScaleEntry Test Start\n");
    osThreadAttr_t attr;

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = CONFIG_TASK_MAIN_STACKSIZE;
    attr.priority = CONFIG_TASK_TASK_PRIOR;
    attr.name = "Task_Thread";
    (void) osThreadNew((osThreadFunc_t)TaskThread, NULL, (const osThreadAttr_t *)&attr);
 

    LedFlashTaskStart();
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = CONFIG_TASK_MAIN_STACKSIZE;
    attr.priority = CONFIG_TASK_DEFAULT_PRIOR;
    attr.name = "MainThread";
    (void) osThreadNew((osThreadFunc_t)MainThread, NULL, (const osThreadAttr_t *)&attr);
}

SYS_RUN(SmartElectronicScaleEntry);
